package com.alibaba.moco.monitor;

import com.alibaba.moco.util.BaseTypeUtil;
import groovy.lang.GroovyObject;
import groovy.util.GroovyScriptEngine;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 磁盘脚本加载类
 * Created by wb-lj240895 on 2016/11/22.
 */
public class ScriptClassLoader {
	private static final Logger logger = LoggerFactory.getLogger(ScriptClassLoader.class);

	private static ConcurrentHashMap<String, GroovyObject> scriptClassMap = new ConcurrentHashMap<String, GroovyObject>();

	private static final String SCRIPT_PATH = BaseTypeUtil.getClassPath() + "script";

	private static GroovyScriptEngine engine = null;

	/**
	 * 获取脚本对象
	 * 
	 * @param scriptName
	 * @return
	 */
	public static GroovyObject getScriptObject(String scriptName) {
		if (scriptClassMap.containsKey(scriptName)) {
			return scriptClassMap.get(scriptName);
		}
		return null;
	}

	/**
	 * 初始化moco脚本
	 */
	public static void init() throws Exception {
		logger.info("正在计划初始化groovy脚本...resoucePath:{},Time:{}", SCRIPT_PATH, System.currentTimeMillis());
		List<File> lstFile = getScriptFiles(new File(SCRIPT_PATH));
		for (File file : lstFile) {
			loadScriptClass(file);
		}
		/*
		 * long interval = TimeUnit.SECONDS.toMillis(5); // 创建一个文件观察器用于处理文件的格式
		 * FileAlterationObserver observer = new FileAlterationObserver(new
		 * File(SCRIPT_PATH)); //设置文件变化监听器 observer.addListener(new
		 * ScriptFileListener()); FileAlterationMonitor monitor = new
		 * FileAlterationMonitor(interval,observer); monitor.start();
		 */
	}

	/**
	 * 必须保证传入的是文件 isFile
	 * 
	 * @param file
	 * @return
	 */
	public static boolean loadScriptClass(File file)
			throws IOException, ResourceException, ScriptException, IllegalAccessException, InstantiationException {
		String scriptName = getScriptName(file);
		Class<?> clasz = getEngine().loadScriptByName(scriptName);
		GroovyObject groovyObject = (GroovyObject) clasz.newInstance();

		scriptClassMap.put(scriptName, groovyObject);
		logger.info("已加载脚本，name:{}", scriptName);
		return true;
	}

	public static GroovyScriptEngine getEngine() throws IOException {
		if (engine == null) {
			/*
			 * synchronized (engine){ if (engine == null) engine = new
			 * GroovyScriptEngine(SCRIPT_PATH); }
			 */
			engine = new GroovyScriptEngine(SCRIPT_PATH);
		}
		return engine;
	}

	public static String getScriptPath() {
		return SCRIPT_PATH;
	}

	/**
	 * 获取目录下所有文件 isFile
	 * 
	 * @param directory
	 * @return
	 */
	private static List<File> getScriptFiles(File directory) {
		List<File> lstFile = new ArrayList<File>();
		if (directory.isDirectory()) {
			File[] files = directory.listFiles();
			for (File file : files) {
				lstFile.addAll(getScriptFiles(file));
			}
		} else if (directory.isFile()) {
			lstFile.add(directory);
		}
		return lstFile;
	}

	/**
	 * 获取执行的脚本名称
	 * 
	 * @param file
	 * @return
	 */
	private static String getScriptName(File file) {
		String fileName = file.getAbsolutePath();
		if (!fileName.startsWith(File.separator)) {
			fileName = File.separator + fileName;
		}
		fileName = fileName.replace("\\", "/");
		String exeScriptName = fileName.replace(SCRIPT_PATH, "");
		if (exeScriptName.startsWith("/")) {
			exeScriptName = StringUtils.removeStart(exeScriptName, "/");
		}
		return exeScriptName;
	}

}
